/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package types;

import java.util.ArrayList;
import java.util.Collection;
import utils.RuleHelper;

/**
 *
 * @author Roman
 */
public class SudokuMatrix<T> implements ISudokuMatrix<T> {

    private int rowCount = 0;
    private int colCount = 0;
    private int boxNum = 0;
    private T[][] data;

    public SudokuMatrix(int rowCount, int colCount) {
        this.rowCount = rowCount;
        this.colCount = colCount;
        this.boxNum = (int) Math.sqrt(rowCount);
        data = (T[][]) new Object[rowCount][colCount];
    }

    public SudokuMatrix(T[][] array) {
        data = (T[][]) array.clone();
        rowCount = array.length;
        colCount = array[0].length;
        boxNum = (int) Math.sqrt(rowCount);
    }

    

    public T getElementAt(int i, int j) {
        return data[i][j];
    }

    public void insertElementAt(T element, int i, int j) {
        data[i][j] = element;
    }

    public int getRowCount() {
        return rowCount;
    }

    public int getColCount() {
        return colCount;
    }

    public int getBoxNum() {
        return boxNum;
    }

    /**
     * Prueft ob der Wert bereits in der (horizontalen) SPALTE existiert
     * @return-> Gibt true zurueck, wenn der Wert bereits existiert
     */
    public boolean checkHorizontal(int j, T element) {
        for (int a = 0; a < colCount; a++) {
            if (data[a][j] == element) {
                return true;
            }
        }
        return false;
    }

    /**
     * Prueft ob der Wert bereits in der (vertikalen) REIHE existiert
     * @return-> Gibt true zurueck, wenn der Wert bereits existiert
     */
    public boolean checkVertical(int i, T element) {
        for (int a = 0; a < rowCount; a++) {
            if (data[i][a] == element) {
                return true;
            }
        }
        return false;
    }
    /**
     * Prueft ob der Wert bereits in der BOX existiert
     * @return-> Gibt true zurueck, wenn der Wert bereits existiert
     */
    public boolean checkBox(int i, int j, T element) {
        // oberes, linkes Eck der Box herausfinden (2|8 zu 0|6)
        int i_start = (int) (i / boxNum) * boxNum;
        int j_start = (int) (j / boxNum) * boxNum;

        for (int a = i_start; a < i_start + boxNum; a++) {
            for (int b = j_start; b < j_start + boxNum; b++) {
                if (data[a][b] == element) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * gibt die Ziffern eines Quadrates zurück
     * @param quadrat
     * @return
     * @throws Exception
     */
    public Collection getQuadratDigits(int quadrat) throws Exception {

        Collection digits = new ArrayList();

        if (quadrat == 1) {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    digits.add( getElementAt(i, j));
                }
            }
            return digits;
        } else if (quadrat == 2) {
            for (int i = 0; i < 3; i++) {
                for (int j = 3; j < 6; j++) {
                    digits.add(getElementAt(i, j));
                }
            }
            return digits;
        } else if (quadrat == 3) {
            for (int i = 0; i < 3; i++) {
                for (int j = 6; j < 9; j++) {
                    digits.add(getElementAt(i, j));
                }
            }
            return digits;
        } else if (quadrat == 4) {
            for (int i = 3; i < 6; i++) {
                for (int j = 0; j < 3; j++) {
                    digits.add(getElementAt(i, j));
                }
            }
            return digits;
        } else if (quadrat == 5) {
            for (int i = 3; i < 6; i++) {
                for (int j = 3; j < 6; j++) {
                    digits.add(getElementAt(i, j));
                }
            }
            return digits;
        } else if (quadrat == 6) {
            for (int i = 3; i < 6; i++) {
                for (int j = 6; j < 9; j++) {
                    digits.add(getElementAt(i, j));
                }
            }
            return digits;
        } else if (quadrat == 7) {
            for (int i = 6; i < 9; i++) {
                for (int j = 0; j < 3; j++) {
                    digits.add(getElementAt(i, j));
                }
            }
            return digits;
        } else if (quadrat == 8) {
            for (int i = 6; i < 9; i++) {
                for (int j = 3; j < 6; j++) {
                    digits.add(getElementAt(i, j));
                }
            }
            return digits;
        } else if (quadrat == 9) {
            for (int i = 6; i < 9; i++) {
                for (int j = 6; j < 9; j++) {
                    digits.add(getElementAt(i, j));
                }
            }
            return digits;
        }
        throw new Exception("invalid field!");

    }
}
